package com.gitee.wsl.common.ui.theme

import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.graphics.drawscope.DrawStyle
import androidx.compose.ui.text.ExperimentalTextApi
import androidx.compose.ui.text.PlatformTextStyle
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontSynthesis
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.*
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.sp
import com.gitee.wsl.data.store.StoreControl
import com.gitee.wsl.data.store.StoreServer
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

interface TypographyScheme {
    var displayLarge: TextStyle
    var displayMedium: TextStyle
    var displaySmall: TextStyle
    var headlineLarge: TextStyle
    var headlineMedium: TextStyle
    var headlineSmall: TextStyle
    var titleLarge: TextStyle
    var titleMedium: TextStyle
    var titleSmall: TextStyle
    var bodyLarge: TextStyle
    var bodyMedium: TextStyle
    var bodySmall: TextStyle
    var labelLarge: TextStyle
    var labelMedium: TextStyle
    var labelSmall: TextStyle

    var h1: TextStyle
    var h2: TextStyle
    var h3: TextStyle
    var h4: TextStyle
    var h5: TextStyle
    var h6: TextStyle

    var subtitle1: TextStyle
    var subtitle2: TextStyle
    var body1: TextStyle
    var body2: TextStyle
    var button: TextStyle
    var caption: TextStyle
    var overline: TextStyle
}

open class DefaultTypographyScheme(
    override var displayLarge: TextStyle = TextStyle.Default,
    override var displayMedium: TextStyle = TextStyle.Default,
    override var displaySmall: TextStyle = TextStyle.Default,

    override var headlineLarge: TextStyle = TextStyle.Default,
    override var headlineMedium: TextStyle = TextStyle.Default,
    override var headlineSmall: TextStyle = TextStyle.Default,

    override var titleLarge: TextStyle = TextStyle.Default,
    override var titleMedium: TextStyle = TextStyle.Default,
    override var titleSmall: TextStyle = TextStyle.Default,

    override var bodyLarge: TextStyle = TextStyle.Default,
    override var bodyMedium: TextStyle = TextStyle.Default,
    override var bodySmall: TextStyle = TextStyle.Default,

    override var labelLarge: TextStyle = TextStyle.Default,
    override var labelMedium: TextStyle = TextStyle.Default,
    override var labelSmall: TextStyle = TextStyle.Default,

    override var h1: TextStyle = TextStyle.Default,
    override var h2: TextStyle = TextStyle.Default,
    override var h3: TextStyle = TextStyle.Default,
    override var h4: TextStyle = TextStyle.Default,
    override var h5: TextStyle = TextStyle.Default,
    override var h6: TextStyle = TextStyle.Default,
    override var subtitle1: TextStyle = TextStyle.Default,
    override var subtitle2: TextStyle = TextStyle.Default,
    override var body1: TextStyle = TextStyle.Default,
    override var body2: TextStyle = TextStyle.Default,
    override var button: TextStyle = TextStyle.Default,
    override var caption: TextStyle = TextStyle.Default,
    override var overline: TextStyle = TextStyle.Default
) : TypographyScheme

val defaultTypography by lazy{
    DefaultTypographyScheme(
        headlineLarge = TextStyle(
            fontWeight = FontWeight.SemiBold,
            fontSize = 32.sp,
            lineHeight = 40.sp,
            letterSpacing = 0.sp
        ),
        headlineMedium = TextStyle(
            fontWeight = FontWeight.SemiBold,
            fontSize = 28.sp,
            lineHeight = 36.sp,
            letterSpacing = 0.sp
        ),
        headlineSmall = TextStyle(
            fontWeight = FontWeight.SemiBold,
            fontSize = 24.sp,
            lineHeight = 32.sp,
            letterSpacing = 0.sp
        ),
        titleLarge = TextStyle(
            fontWeight = FontWeight.SemiBold,
            fontSize = 22.sp,
            lineHeight = 28.sp,
            letterSpacing = 0.sp
        ),
        titleMedium = TextStyle(
            fontWeight = FontWeight.SemiBold,
            fontSize = 16.sp,
            lineHeight = 24.sp,
            letterSpacing = 0.15.sp
        ),
        titleSmall = TextStyle(
            fontWeight = FontWeight.Bold,
            fontSize = 14.sp,
            lineHeight = 20.sp,
            letterSpacing = 0.1.sp
        ),
        bodyLarge = TextStyle(
            fontWeight = FontWeight.Normal,
            fontSize = 16.sp,
            lineHeight = 24.sp,
            letterSpacing = 0.15.sp
        ),
        bodyMedium = TextStyle(
            fontWeight = FontWeight.Medium,
            fontSize = 14.sp,
            lineHeight = 20.sp,
            letterSpacing = 0.25.sp
        ),
        bodySmall = TextStyle(
            fontWeight = FontWeight.Bold,
            fontSize = 12.sp,
            lineHeight = 16.sp,
            letterSpacing = 0.4.sp
        ),
        labelLarge = TextStyle(
            fontWeight = FontWeight.SemiBold,
            fontSize = 14.sp,
            lineHeight = 20.sp,
            letterSpacing = 0.1.sp
        ),
        labelMedium = TextStyle(
            fontWeight = FontWeight.SemiBold,
            fontSize = 12.sp,
            lineHeight = 16.sp,
            letterSpacing = 0.5.sp
        ),
        labelSmall = TextStyle(
            fontWeight = FontWeight.SemiBold,
            fontSize = 11.sp,
            lineHeight = 16.sp,
            letterSpacing = 0.5.sp
        )
    )
}

class SubTypographyProp(val base:()-> TextStyle): ReadWriteProperty<Any, TextStyle> {
    var cache: TextStyle?=null

    override fun getValue(thisRef: Any, property: KProperty<*>): TextStyle {
        return  cache?:base().merge(cache)
    }

    override fun setValue(thisRef: Any, property: KProperty<*>, value: TextStyle) {
        cache = value
    }

    operator fun getValue(nothing: Nothing?, property: KProperty<*>): TextStyle {
        return  cache?:base().merge(cache)
    }

    operator fun setValue(nothing: Nothing?, property: KProperty<*>, textStyle: TextStyle) {
        cache = textStyle
    }

}


class SubTypographySaveAbleProp<T>(var cache:T?, val base:()->T): ReadWriteProperty<Any, T> {
    override fun getValue(thisRef: Any, property: KProperty<*>): T {
        return  cache?:base()
    }

    override fun setValue(thisRef: Any, property: KProperty<*>, value: T) {
        cache = value
    }
}



fun TextStyle.merge(warpHandler: TextStyleConfig.() -> Unit): TextStyle {
    val config= TextStyleConfig()
    warpHandler(config)
    return this.merge(config.toTextStyle())
}

fun TextStyle.subTextStyle(warpHandler: TextStyleConfig.() -> Unit):TextStyle{
    return subTextStyle(getBase = {this}, warpHandler )
}

inline fun textStyle(warpHandler: TextStyleConfig.() -> Unit): TextStyle {
    val config= TextStyleConfig()
    warpHandler(config)
    return config.toTextStyle()
}

inline fun subTextStyle(noinline getBase:()->TextStyle, warpHandler: TextStyleConfig.() -> Unit):TextStyle{
    val config= TextStyleConfig()
    var subTextStyle :TextStyle by SubTypographyProp( base = getBase)
    warpHandler(config)
    subTextStyle=config.toTextStyle()
    return subTextStyle
}

open class SubTypography(base:()-> TypographyScheme): SubTypographyScheme<TypographyScheme>(base)

open class SubTypographyScheme<T: TypographyScheme>( val base:()->T) : TypographyScheme,
    StoreControl {

    companion object{
        val STORE_TYPOGRAPHY_LABEL="STORE_TYPOGRAPHY_LABEL"
    }

    override fun saveToStore(server: StoreServer) {
    }

    override fun reStore(server: StoreServer) {
    }

    override var displayLarge: TextStyle by SubTypographyProp{
        base().displayLarge
    }
    override var displayMedium: TextStyle by SubTypographyProp{
        base().displayMedium
    }
    override var displaySmall: TextStyle by SubTypographyProp{
        base().displaySmall
    }
    override var headlineLarge: TextStyle by SubTypographyProp{
        base().headlineLarge
    }
    override var headlineMedium: TextStyle by SubTypographyProp{
        base().headlineMedium
    }
    override var headlineSmall: TextStyle by SubTypographyProp{
        base().headlineSmall
    }
    override var titleLarge: TextStyle by SubTypographyProp{
        base().titleLarge
    }
    override var titleMedium: TextStyle by SubTypographyProp{
        base().titleMedium
    }
    override var titleSmall: TextStyle by SubTypographyProp{
        base().titleSmall
    }
    override var bodyLarge: TextStyle by SubTypographyProp{
        base().bodyLarge
    }
    override var bodyMedium: TextStyle by SubTypographyProp{
        base().bodyMedium
    }
    override var bodySmall: TextStyle by SubTypographyProp{
        base().bodySmall
    }
    override var labelLarge: TextStyle by SubTypographyProp{
        base().displayLarge
    }
    override var labelMedium: TextStyle by SubTypographyProp{
        base().labelMedium
    }
    override var labelSmall: TextStyle by SubTypographyProp{
        base().labelSmall
    }
    override var h1: TextStyle by SubTypographyProp{
        base().h1
    }
    override var h2: TextStyle by SubTypographyProp{
        base().h2
    }
    override var h3: TextStyle by SubTypographyProp{
        base().h3
    }
    override var h4: TextStyle by SubTypographyProp{
        base().h4
    }
    override var h5: TextStyle by SubTypographyProp{
        base().h5
    }
    override var h6: TextStyle by SubTypographyProp{
        base().h6
    }
    override var subtitle1: TextStyle by SubTypographyProp{
        base().subtitle1
    }
    override var subtitle2: TextStyle by SubTypographyProp{
        base().subtitle2
    }
    override var body1: TextStyle by SubTypographyProp{
        base().body1
    }
    override var body2: TextStyle by SubTypographyProp{
        base().body2
    }
    override var button: TextStyle by SubTypographyProp{
        base().button
    }
    override var caption: TextStyle by SubTypographyProp{
        base().caption
    }
    override var overline: TextStyle by SubTypographyProp{
        base().overline
    }
}

/*open class ComposeTypography(
    override var displayLarge: TextStyle = TypographyTokens.DisplayLarge,
    override var displayMedium: TextStyle = TypographyTokens.DisplayMedium,
    override var displaySmall: TextStyle = TypographyTokens.DisplaySmall,
    override var headlineLarge: TextStyle = TypographyTokens.HeadlineLarge,
    override var headlineMedium: TextStyle = TypographyTokens.HeadlineMedium,
    override var headlineSmall: TextStyle = TypographyTokens.HeadlineSmall,
    override var titleLarge: TextStyle = TypographyTokens.TitleLarge,
    override var titleMedium: TextStyle = TypographyTokens.TitleMedium,
    override var titleSmall: TextStyle = TypographyTokens.TitleSmall,
    override var bodyLarge: TextStyle = TypographyTokens.BodyLarge,
    override var bodyMedium: TextStyle = TypographyTokens.BodyMedium,
    override var bodySmall: TextStyle = TypographyTokens.BodySmall,
    override var labelLarge: TextStyle = TypographyTokens.LabelLarge,
    override var labelMedium: TextStyle = TypographyTokens.LabelMedium,
    override var labelSmall: TextStyle = TypographyTokens.LabelSmall
):com.gitee.wsl.common.ui.ext.Typography*/

class TextStyleConfig{
    var brush: Brush?=null
    var alpha: Float = Float.NaN
    var fontSize: TextUnit = TextUnit.Unspecified
    var fontWeight: FontWeight? = null
    var fontStyle: FontStyle? = null
    var fontSynthesis: FontSynthesis? = null
    var fontFamily: FontFamily? = null
    var fontFeatureSettings: String? = null
    var letterSpacing: TextUnit = TextUnit.Unspecified
    var baselineShift: BaselineShift? = null
    var textGeometricTransform: TextGeometricTransform? = null
    //var localeList: LocaleList? = null,
    var background: androidx.compose.ui.graphics.Color = androidx.compose.ui.graphics.Color.Unspecified
    var textDecoration: TextDecoration? = null
    var shadow: Shadow? = null
    var drawStyle: DrawStyle? = null
    var textAlign: TextAlign? = null
    var textDirection: TextDirection? = null
    var lineHeight: TextUnit = TextUnit.Unspecified
    var textIndent: TextIndent? = null
    var platformStyle: PlatformTextStyle? = null
    var lineHeightStyle: LineHeightStyle? = null
    //var lineBreak: LineBreak? = null,
    //var hyphens: Hyphens? = null,
    //var textMotion: TextMotion? = null

    @OptIn(ExperimentalTextApi::class)
    fun toTextStyle(): TextStyle {
        return TextStyle(
            brush=brush,
            alpha=alpha,
            fontSize=fontSize,
            fontWeight=fontWeight,
            fontStyle=fontStyle,
            fontSynthesis=fontSynthesis,
            fontFamily=fontFamily,
            fontFeatureSettings=fontFeatureSettings,
            letterSpacing=letterSpacing,
            baselineShift=baselineShift,
            textGeometricTransform=textGeometricTransform,
            localeList = null,
            background=background,
            textDecoration=textDecoration,
            shadow=shadow,
            textAlign = textAlign?:TextAlign.Center,
            textDirection = textDirection?:TextDirection.Unspecified,
            lineHeight = lineHeight,
            textIndent = textIndent,
            platformStyle = platformStyle
        )
    }
}


